#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys
import argparse
import paramiko

def get_groups(file):
    """ 主机组列表 """
    groups_dict = {}
    with open(file,'r') as f:
        key = 'hosts'
        groups_dict['hosts'] = []
        for line in f.readlines():
            tmp_line = line.strip()
            # 去除无用行
            if tmp_line.startswith("#") or tmp_line.startswith(";") or len(tmp_line) == 0:
                continue
            if tmp_line.find('[') == 0 and tmp_line.find(']') == len(tmp_line) - 1:
                # key值产生变量替换
                key = tmp_line.lstrip('[').rstrip(']')
                # 添加主机组
                groups_dict[key] = []
            else:
                # 向主机组添加主机
                groups_dict[key].append(tmp_line)
    return groups_dict

class Hosts(object):
    """ 主机列表 """

    def __init__(self, groups):
        self.groups = groups
        self.hosts = []

    def get_hosts(self):
        """ 获取主机列表 """
        all_vars = {} # 主机全局变量, 格式:{'ansible_ssh_port': '22', 'ansible_ssh_user': 'root', 'ansible_ssh_pass': 'p0o9i8u7y6'}
        for hvar in self.groups['all:vars']: #全局变量
            hvar_kv = hvar.split('=')
            if len(hvar_kv) == 2:
                all_vars[hvar_kv[0]] = hvar_kv[1]
        print('all_vars: %s' % str(all_vars) )
        host_dict = {} #主机信息集合, [{'host': '192.168.150.123' , 'ansible_ssh_port': '22', 'ansible_ssh_user': 'root', 'ansible_ssh_pass': 'p0o9i8u7y6'},...]
        hosts_vars = self.groups['hosts'] #主机列表
        for item in hosts_vars: 
            host_list_item = item.split(' ')
            host_dict = all_vars.copy()
            for host_item in host_list_item:
                if host_item.find('=') >= 0:
                    tmp = host_item.strip().split('=')              
                    host_dict[tmp[0]] = tmp[1]
            if len(host_dict) < 3:
                raise Exception('Missing host information[ host or user or password or keyfile]! all:vars => %s, host => %s ' % (str(host_dict), str(hosts_vars)))
            self.hosts.append({'host': host_dict.get('ansible_ssh_host'), 
                               'port': int(host_dict.get('ansible_ssh_port')),
                               'user': host_dict.get('ansible_ssh_user'),
                               'passwd': host_dict.get('ansible_ssh_pass'),
                               'sudo_passwd': host_dict.get('ansible_sudo_pass'),
                               'key_file': host_dict.get('ansible_ssh_private_key_file')})
        print('host_dict: %s' % str(self.hosts) )

class SSHConnection(object):
    """ 远程操作 """

    def __init__(self, host, port, user, password):
        self.host = host
        self.port = port
        self.user = user
        self.password = password

    def get_client(self):
        # try:
        self.ssh = paramiko.SSHClient()
        self.ssh.load_system_host_keys()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # print(self.host, self.port, self.user, self.password)
        try:
            if os.path.isfile(self.password):
                private_key = paramiko.RSAKey.from_private_key_file(self.password)
                self.ssh.connect(self.host, self.port, self.user, pkey=private_key)
            else:
                self.ssh.connect(self.host, self.port, self.user, self.password)
            return True
        except Exception as err:
            print("\n\033[31mhost:%s, connect error:%s\033[0m" % (self.host, err))
            self.close()
            return False

    def cmd(self, command):
        try:
            stdin, stdout, stderr = self.ssh.exec_command(command)
            return stdout.read()
        except AttributeError as err:
            print('AttributeError:\t %s' % err)

    def close(self):
        self.ssh.close()


def check_info(hosts_ssh):
    for ssh in hosts_ssh:
        if ssh.get_client():
            print("----------------------------------------------------")
            hostname = ssh.cmd("hostname").strip()
            print('hostname:\t%s' % hostname)
            print('IP_addr:\t%s' % ssh.host)
            dtime = ssh.cmd("date +'%Y-%m-%d %H:%M:%S'").strip()
            print('date: \t\t%s' % dtime)
            os_info = ssh.cmd('cat /etc/redhat-release |head -n 1').strip()
            os_info = os_info + "\t" + ssh.cmd('uname -r').strip()
            print('os: \t\t%s' % os_info)
            cpu = ssh.cmd("lscpu  |sed -n '4p'").strip().replace(' ', '')
            print('cpu: \t\t%s' % cpu)
            memory = ssh.cmd('free -g |grep Mem |awk \'{print $1 "\t\ttotal " $2 "G" "\tavailable " $NF "G"}\'').strip()
            print('%s' % memory)
            Swap = ssh.cmd('free -g |grep Swap |awk \'{print $1 " \t\ttotal " $2 "G" "\tfree " $NF "G"}\'').strip()
            print('%s' % Swap)
            disk_info = ssh.cmd('parted -l |grep "^Disk /dev" | awk \'{print $2, $3}\' |sed  \'s/:/\t/\'').strip()

            print('- disk_total: \n%s' % disk_info)
            disk_mount = ssh.cmd('df -hT |egrep -v "(docker|tmpfs|^$)"').strip()
            print('- disk_used: \n%s' % disk_mount)
            if ssh.cmd("df -hT /data |awk '{ if (NR >1) print $2 }'").strip() == "xfs":
                xfs_info = ssh.cmd('xfs_info /data')
                if "ftype=1" not in xfs_info:
                    print('- fs_info:\n\033[31m%s\033[0m' % xfs_info)
                else:
                    print('- fs_info:\n\033[32m%s\033[0m' % xfs_info)

            sysctl_cfg = ssh.cmd('/sbin/sysctl -a')
            # print('sysctl.conf\n%s' % sysctl_cfg)
            file_name = "../logs/%s_sysctl.conf" % hostname
            with open(file_name, "wb") as f:
                f.write(sysctl_cfg + '\n')
                f.flush()
            print("----------------------------------------------------")


def init_ssh(args):
    """ 通过hosts.ini文件进行检查 """

    # 获取主机组
    groups = get_groups(args.file)
    # 获取主机列表和登陆账号信息
    servers = Hosts(groups)
    servers.get_hosts()
    hosts_ssh = []
    for item in servers.hosts:
        if item.get('key_file'):
            ssh = SSHConnection(item['host'], item['port'], item['user'], item['key_file'])
        else:
            ssh = SSHConnection(item['host'], item['port'], item['user'], item['passwd'])
        hosts_ssh.append(ssh)
    return hosts_ssh


def check_docker(hosts_ssh):
    docker_exists_hosts = []
    for ssh in hosts_ssh:
        if ssh.get_client():
            result = ssh.cmd("if [ -f \"/var/run/docker.pid\" ]; then echo true; else echo false; fi")
            if 'true' in result:
                docker_exists_hosts.append(ssh.host)

    if len(docker_exists_hosts) > 0:
        print('%s 机器上docker服务已经启动' % docker_exists_hosts)
        status = raw_input("请确认是否继续安装[y/n]：")
        if str(status).upper() != 'Y':
            sys.exit(-1)


def close_sshs(hosts_ssh):
    for ssh in hosts_ssh:
        ssh.close()


if __name__ == "__main__":
    '''  '''
    base_dir = os.getcwd()
    parse = argparse.ArgumentParser()
    parse.add_argument('--file', type=str, default=base_dir + "/../hosts.ini", help='指定hosts.ini文件')
    parse.add_argument('--opt', type=str, default="info", help='判断检查机器信息,或docker服务;[info|docker]')
    args = parse.parse_args()
    if os.path.isfile(args.file) and args.file.endswith(".ini"):
        hosts_ssh = init_ssh(args)
    else:
        print('please use command "python %s -h" for help.' % os.path.basename(sys.argv[0]))
        sys.exit(-1)

    if args.opt.upper() == 'INFO':
        check_info(hosts_ssh)
    elif args.opt.upper() == 'DOCKER':
        check_docker(hosts_ssh)

    # 关闭所有ssh连接
    close_sshs(hosts_ssh)
